#include "bmp.h"

static unsigned int *lcd_p 		;			//lcd映射空间内存的指针
static unsigned int *temp_p 	;			//lcd映射空间内存的指针
static int lcd_fd 				;			//lcd的文件描述符

//1、打开lcd屏幕(bmp、申请lcd的所需内存空间，且初始化)
void Bmp_Lcd_Open(void)
{
	//1、打开lcd显示屏文件(以只写的形式的打开)
	lcd_fd = open("/dev/fb0", O_RDWR);
	if (-1 == lcd_fd){
		perror("open lcd error!\n");
		return ;
	}


	//2、将ARGB数据(lcd)写入到lcd显示屏上
	lcd_p = mmap(
					NULL,  					//内核会自动分配地址
					800*480*4,				//lcd映射内存空间的长度(大小)
					PROT_READ|PROT_WRITE, 	//该映射空间可被读/写
					MAP_SHARED, 			//该映射空间可被其它进程访问
					lcd_fd,					//lcd的文件描述符
					0						//映射内存空间一开始的位置
				);
	if ((void *) -1 == lcd_p)
	{
		perror("mmap lcd error!\n");
		return ;
	}

	temp_p = lcd_p;							//记住lcd_p指针最初指向内存的地址的位置

	return ;

}

//2、显示bmp图片(任意大小位置图片显示)
void Bmp_Show(int lcd_x, int lcd_y, int bmp_x, int bmp_y, char *bmp_path)
{
	//===========一、获取bmp图片的颜色数据(BGR数据)==========//
	//1、打开bmp图片文件(以只读的形式打开)
	int bmp_fd = open(bmp_path, O_RDONLY);
	if (-1 == bmp_fd){
		perror("open bmp error!\n");
		return ;
	}

	//2、获取bmp图片的大小
	off_t bmp_filesize = lseek(bmp_fd, 0, SEEK_END);
	if ((off_t)-1 == bmp_filesize){
		perror("lseek bmp end error!\n");
		return ;
	}
	else
		printf("1、bmp图片的数据大小为%ld字节\n",  bmp_filesize);

	//3、跳过bmp图片的头信息数据(54个字节)
	off_t ret_l = lseek(bmp_fd, 54, SEEK_SET);
	if ((off_t) -1 == ret_l){
		perror("lseek bmp 54 error!\n");
		return ;
	}

	//4、读取bmp图片的颜色数据
	char bmp_buf[bmp_x*bmp_y*3];
	bzero(bmp_buf, sizeof(bmp_buf));
	ssize_t ret_r = read(bmp_fd, bmp_buf, sizeof(bmp_buf));
	if (-1 == ret_r){
		perror("read bmp error!\n");
		return ;
	}
	else
		printf("2、读到bmp图片大小为:%d字节\n", ret_r);

	//5、关闭bmp图片文件
	int ret_c = close(bmp_fd);
	if (-1 == ret_c){
		perror("close bmp error!\n");
		return ;
	}


	//=========二、将BGR数据(bmp)转换成ARGB数据(lcd)=========//
	int lcd_buf[bmp_x*bmp_y];
	bzero(lcd_buf, sizeof(lcd_buf));
	int i = 0;
	for(i=0; i<bmp_x*bmp_y; i++)
		lcd_buf[i] = (bmp_buf[i*3]<<0) + (bmp_buf[i*3+1]<<8)  + (bmp_buf[i*3+2]<<16) + (0x00<<24);
	     // ARGB             B                 G                     R                 A
		 


	//=========三、将ARGB数据(lcd)显示到lcd显示屏上==========//
	//1、任意位置显示bmp图片
	lcd_p = lcd_p + lcd_x;					//指定x轴的显示位置
	lcd_p = lcd_p + lcd_y*800;				//指定y轴的显示位置


	//2、任意大小显示bmp图片
	int x,y;
	for(y=0; y<bmp_y; y++)
	{
		for(x=0; x<bmp_x; x++)
		{
			*(lcd_p+(bmp_y-y-1)*800+x) = lcd_buf[y*bmp_x+x];
		}
	}

	lcd_p = temp_p;							//让lcd_p重新回到最初指向内存的地址的位置
	return ;
}


//3、关闭lcd显示屏(释放内存、资源)
void Bmp_Lcd_Close(void)
{
	//1、解除映射lcd空间
	int ret_mun = munmap(lcd_p, 800*480*4);
	if (-1 == ret_mun)
	{
		perror("munmap lcd error!\n");
		return ;
	}

	//2、关闭lcd显示屏文件
	int ret_c = close(lcd_fd);
	if ( -1 ==ret_c){
		perror("close lcd error!\n");
		return ;
	}

	return ;
}
